package me.aip.mov.handler;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import io.netty.handler.codec.http.HttpHeaders;
import io.netty.handler.timeout.IdleStateEvent;
import me.aip.mov.constant.Constant;
import me.aip.mov.controller.vo.ReturnMsg;
import me.aip.mov.entity.ChatMsg;
import me.aip.mov.service.IChatMsgService;
import me.aip.mov.util.EmojiUtil;
import me.aip.mov.util.RedisUtil;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.util.MultiValueMap;
import org.springframework.web.client.RestTemplate;
import org.yeauty.annotation.*;
import org.yeauty.pojo.Session;
import java.io.IOException;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;


@ServerEndpoint(path = "/ws/{userno}",host = "${ws.host}",port = "${ws.port}")
public class WebSocket {

    // 这里使用静态，让 service 属于类
    @Autowired
    private IChatMsgService chatMsgService;
    @Autowired
    private RestTemplate restTemplate;



    private static ConcurrentHashMap<String, WebSocket> webSocketSet = new ConcurrentHashMap<String, WebSocket>();

    //静态变量，用来记录当前在线连接数。应该把它设计成线程安全的。
    private static int onlineCount = 0;

    private Session WebSocketsession;
    //当前发消息的人员编号
    private String userno = "";

    @BeforeHandshake
    public void handshake(Session session, HttpHeaders headers, @RequestParam String req, @RequestParam MultiValueMap reqMap, @PathVariable String arg, @PathVariable Map pathMap){
          String token = headers.get("Authorization");
          if (token == null){
              System.out.println("Authentication failed!");
              session.close();
              return;
          }
        String tokenKey = Constant.Redis.TOKEN_PREFIX + token;
        String cacheToken = RedisUtil.StringOps.get(tokenKey);
          if (cacheToken == null){
              System.out.println("Authentication failed!");
              session.close();
              return;
          }
    }


    @OnOpen
    public void onOpen(Session session, HttpHeaders headers, @RequestParam String req, @RequestParam MultiValueMap reqMap, @PathVariable String userno, @PathVariable Map pathMap){
        this.WebSocketsession = session;
        webSocketSet.put(userno, this);//加入map中
        addOnlineCount();     //在线数加1
    }

    @OnClose
    public void onClose(Session session) throws IOException {
        System.out.println("one connection closed");
        webSocketSet.remove(userno);//加入map中

    }

    @OnError
    public void onError(Session session, Throwable throwable) {
          webSocketSet.remove(userno);
          throwable.printStackTrace();
    }

    @OnMessage
    public void onMessage(Session session, String chatmsg) {
        ChatMsg chatMsg = JSON.parseObject(chatmsg, ChatMsg.class);
        //给指定的人发消息
        sendToUser(chatMsg);

    }
    /**
     * 给指定的人发送消息
     *
     * @param chatMsg 消息对象
     */
    public void sendToUser(ChatMsg chatMsg) {
        String fromUserid = chatMsg.getFromUserid();
        String toUserid = chatMsg.getToUserid();
        String sendMessage = EmojiUtil.filterEmoji(chatMsg.getContent());
        chatMsg.setContent(sendMessage);
        if(!"ping".equals(chatMsg.getType())){
            chatMsgService.save(chatMsg);
        }
        if (webSocketSet.get(toUserid) != null) {
            webSocketSet.get(toUserid).WebSocketsession.sendText(JSON.toJSONString(chatMsg));
        }else{
            //客服id 未存储数据库
            chatMsg.setId(null);
            chatMsg.setFromUserid(toUserid);
            chatMsg.setToUserid(fromUserid);
            chatMsg.setType("text");
            chatMsg.setStatus(1);
            chatMsg.setAuto(1);
            String returnMsg = this.siZhiChatMsg(fromUserid,sendMessage);
            returnMsg=returnMsg.replaceAll("小思","盼盼");
            chatMsg.setContent(returnMsg);
            chatMsgService.save(chatMsg);
            webSocketSet.get(fromUserid).WebSocketsession.sendText(JSON.toJSONString(chatMsg));
        }

    }

    //AI聊天接口 qingyunke
    public String aiChatMsg(String msg){
        String resp = restTemplate.getForObject("https://api.qingyunke.com/api.php?key=free&appid=0&msg="+msg, String.class);
        if (resp != null){
            return JSON.parseObject(resp).getString("content");
        }
        return null;
    }
//AI聊天接口 https://www.ownthink.com/docs/bot/
    public String siZhiChatMsg(String userId,String msg){
        String resp = restTemplate.getForObject("https://api.ownthink.com/bot?appid=9e8f934e901256f0199e9aa18f443ccd&userid=uKFwz7TJ&spoken="+msg, String.class);
        if (resp != null){
            String data = JSON.parseObject(resp).getString("data");
            String info = JSON.parseObject(data).getString("info");
            return JSON.parseObject(info).getString("text") ;
        }
        return null;
    }


    /**
     * 给所有人发消息
     *
     * @param message
     */
    private void sendAll(String message) {
        String sendMessage = message.split("[|]")[1];
        //遍历HashMap
        for (String key : webSocketSet.keySet()) {
            //判断接收用户是否是当前发消息的用户
            if (!userno.equals(key)) {
                webSocketSet.get(key).WebSocketsession.sendText(sendMessage);
                System.out.println("key = " + key);
            }
        }
    }
    @OnBinary
    public void onBinary(Session session, byte[] bytes) {
        for (byte b : bytes) {
            System.out.println(b);
        }
        session.sendBinary(bytes);
    }

    @OnEvent
    public void onEvent(Session session, Object evt) {
        if (evt instanceof IdleStateEvent) {
            IdleStateEvent idleStateEvent = (IdleStateEvent) evt;
            switch (idleStateEvent.state()) {
                case READER_IDLE:
                    System.out.println("read idle");
                    break;
                case WRITER_IDLE:
                    System.out.println("write idle");
                    break;
                case ALL_IDLE:
                    System.out.println("all idle");
                    break;
                default:
                    break;
            }
        }
    }


    public static synchronized void addOnlineCount() {
        WebSocket.onlineCount++;
    }
}
